package io.xiaojl.xj2ee.aop;

import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cz.mallat.uasparser.OnlineUpdater;
import cz.mallat.uasparser.UASparser;
import cz.mallat.uasparser.UserAgentInfo;
import io.xiaojl.xj2ee.common.kit.WebKit;
import io.xiaojl.xj2ee.common.kit.json.JsonKit;
import io.xiaojl.xj2ee.kit.SessionKit;
import io.xiaojl.xj2ee.modules.sys.entity.SysUserEntity;

/**
 * 
 * <p>Title: AccessLogAop</p>  
 *
 * <p>Description: 记录访问日志</p>  
 *
 * @author jilong.xiao  
 * @date 2018年5月28日
 */
@Component
@Aspect
public class AccessLogAop {
	private static final Logger log = LoggerFactory.getLogger(AccessLogAop.class);
	static UASparser uasParser = null;
	
	static {// 初始化uasParser对象
		try {
			uasParser = new UASparser(OnlineUpdater.getVendoredInputStream());
		} catch (IOException e) {
			log.error("", e);
		}
	}

	/**
	 * 定义拦截规则
	 */
//	@Pointcut("@within(org.springframework.stereotype.Controller)")
	@Pointcut("@within(org.springframework.stereotype.Controller)||@within(org.springframework.web.bind.annotation.RestController)")
	public void webRequestLog() {
	}

	/**
	 * 拦截器具体实现
	 */
	@Around("webRequestLog()")
	public Object aroundLog(ProceedingJoinPoint joinPoint) throws Throwable {
		//访问日志信息map
		Map<String,Object> accessLogMap = new HashMap<String,Object>();
		
		long beginTime = System.currentTimeMillis();
		// 接收到请求，记录请求内容
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		String uri = request.getRequestURI();
		// 获取客户端信息
		String userAgent = "";
		try {
			UserAgentInfo userAgentInfo = uasParser.parse(request.getHeader("user-agent"));
			userAgent = userAgentInfo.getOsName() + " " + userAgentInfo.getType() + " " + userAgentInfo.getUaName();
			String optUser = "";
			Long optUserId = -1L;
			SysUserEntity currentUser = SessionKit.getCurrentUser();
			if(currentUser!=null){
				optUser = currentUser.getUsername();
				optUserId = currentUser.getUserId();
			}
			accessLogMap.put("optUserId", optUserId);
			accessLogMap.put("optUser", optUser);
		} catch (IOException e) {
			log.error("获取客户端信息，出现异常：" + e.getLocalizedMessage());
		}
		Signature sign = joinPoint.getSignature();
		String beanName = sign.getDeclaringTypeName();
		String methodName = sign.getName();
		
		accessLogMap.put("optDate", new Date());
		accessLogMap.put("clientIp", WebKit.getRequestId(request));
		accessLogMap.put("clientInfo", userAgent);
		
		String method = request.getMethod();
		String params = getRequestParametersKeyValue(request);
//		String optContent = "请求方式：%s 请求地址:%s 类名：%s 方法：%s 参数：%s";
//		accessLogMap.put("optContent",String.format(optContent, method, uri, beanName, methodName, params));
		accessLogMap.put("requestMethod", method);
		accessLogMap.put("requestUri", uri);
		accessLogMap.put("className", beanName);
		accessLogMap.put("methodName", methodName);
		accessLogMap.put("params", params);

		// 返回结果
		Object result = null;
		try {
			result = joinPoint.proceed();// 执行业务逻辑方法，得到响应结果
			accessLogMap.put("resultCode","200");
			accessLogMap.put("resultText",JsonKit.toJson(result));
			long requestTime = System.currentTimeMillis() - beginTime;
			accessLogMap.put("time",requestTime);

		} catch (Throwable e) {
			long requestTime = System.currentTimeMillis() - beginTime;
			accessLogMap.put("resultCode","500");
			accessLogMap.put("resultText","出现异常：" + e.getMessage());
			accessLogMap.put("time",requestTime);
			throw e;// 抛出异常，从而方便Controller层统一进行异常处理
		} finally {
			if (log.isDebugEnabled()) {
				log.debug("访问日志：{}", JsonKit.toJson(accessLogMap));
			}
			log.debug("--------访问日志 -> 不存入DB-------------");
//			if (!uri.contains("/read/") && !uri.contains("/unauthorized") && !uri.contains("/forbidden")
//					&& !uri.contains("/swagger-resources")) {
//				// 保存DB
//				log.debug("--------访问日志 -> 存入DB-------------");
//			} else {
//				// 非关键操作的正常日志，就不存入DB
//				log.debug("--------访问日志 -> 不存入DB-------------");
//			}
		}
		return result;
	}
	
	/**
	 * <p>Title: getRequestParametersKeyValue</p>  
	 * <p>Description: 获取请求参数的key-value对</p>  
	 *
	 * @param request
	 * @return
	 */
	private String getRequestParametersKeyValue(HttpServletRequest request) {
		Enumeration<String> pNames = request.getParameterNames();
		String keyToValueStr = "";
		while (pNames.hasMoreElements()) {
			String name = (String) pNames.nextElement();
			String value = request.getParameter(name);
			keyToValueStr += name + "=" + value + "&";
		}
		if (keyToValueStr.length() >= 1) {
			keyToValueStr = keyToValueStr.substring(0, keyToValueStr.length() - 1);
		}
		pNames = null;
		return keyToValueStr;
	}
}
